package org.example.service.domain.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.constant.RedisCacheConstant;
import org.example.convert.UserConvert;
import org.example.domain.dto.RegisterDto;
import org.example.domain.dto.SysUserDto;
import org.example.domain.entity.SocialUserRel;
import org.example.domain.entity.SysUser;
import org.example.domain.vo.LoginResultVo;
import org.example.enmus.LoginTypeEnum;
import org.example.exception.BizException;
import org.example.mapper.SysUserMapper;
import org.example.service.domain.RedisServer;
import org.example.service.domain.SocialUserRelService;
import org.example.service.domain.SysUserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;

/**
* @author YINDINGJIE
* @description 针对表【sys_user(系统用户表)】的数据库操作Service实现
* @createDate 2023-11-29 13:55:50
*/
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
    implements SysUserService{

    @Value("${register.html}")
    private String registerUrl;
    
    @Resource
    private RedisServer redisServer;

    @Resource
    private SocialUserRelService socialUserRelService;

    @Resource
    private SysUserMapper sysUserMapper;
  

    @Override
    public LoginResultVo loginResult(Long userId,Integer loginType) {
        String key = LoginTypeEnum.getKeyByType(loginType);
        StpUtil.login(userId,key);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        String tokenName = tokenInfo.getTokenName();
        String tokenValue = tokenInfo.getTokenValue();
        List<String> permissionList = StpUtil.getPermissionList();
        List<String> roleList = StpUtil.getRoleList();
        SysUserDto sysUserDto = selectUserInfoByUserSid(userId);
        if (Objects.isNull(sysUserDto)) {
            throw new BizException("未找到用户信息");
        }
        LoginResultVo resultVo = new LoginResultVo();
        resultVo.setTokenName(tokenName)
                .setTokenValue(tokenValue)
                .setUsername(sysUserDto.getUsername())
                .setRoles(roleList)
                .setPermission(permissionList);
        return resultVo;
    }

    @Override
    public SysUser selectSysUserById(Long userId) {
        return lambdaQuery().eq(SysUser::getId, userId).one();
    }

    @Override
    public LoginResultVo registerByThirdParity(String socialId, String uuid)  {
        String key =  RedisCacheConstant.REGISTER_THIRD_PARITY + uuid;
        redisServer.set(key,socialId);
        HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
        try {
            //TODO 目前写死的，都是pc端的注册
            response.sendRedirect(registerUrl + "?uuid=" + uuid);
        } catch (Exception e) {
            throw new BizException("重定向到注册页面失败");
        }
        return null;
    }

    @Override
    public SysUserDto getLoginUserInfo() {
        long userId = StpUtil.getLoginIdAsLong();
        return redisServer.get(RedisCacheConstant.LOGIN_USER + userId, selectUserDtoByUserId(userId), SysUserDto.class);
    }

    @Override
    public SysUserDto selectUserDtoByUserId(Long userId) {
        return null;
    }

    @Override
    @Transactional
    public void register(RegisterDto registerDto) {
        //校验用户
        validationUser(registerDto);
        //保存用户
        SysUser sysUser = UserConvert.INSTANCE.convert(registerDto);
        save(sysUser);
        String uuid = registerDto.getUuid();
        if (StrUtil.isNotBlank(uuid)) {
            //第三方注册
            String socialId = redisServer.get(RedisCacheConstant.REGISTER_THIRD_PARITY + uuid, String.class);
            if (StrUtil.isNotBlank(socialId)) {
                Integer loginType = registerDto.getLoginType();
                SocialUserRel socialUserRel = socialUserRelService.selectBySocialIdAndLoginType(socialId, loginType);
                if (null != socialUserRel) {
                    throw new BizException("用户已注册,请勿重复注册");
                }
                Long id = sysUser.getId();
                SocialUserRel rel = new SocialUserRel();
                rel.setUserId(id);
                rel.setSocialId(socialId);
                rel.setType(loginType);
                socialUserRelService.save(rel);
            }  
        }
    }

    @Override
    public SysUserDto selectUserInfoByUserSid(Long userId) {
        return sysUserMapper.selectUserDtoByUserSid(userId);
    }

    private void validationUser(RegisterDto registerDto) {
        String account = registerDto.getAccount();
        Integer loginType = registerDto.getLoginType();
        SysUser sysUser = selectByAccountAndLoginType(account, loginType);
        if (Objects.nonNull(sysUser)) {
            throw new BizException("改账户已注册");
        }
    }

    @Override
    public SysUser selectByAccountAndLoginType(String account, Integer loginType) {
        return lambdaQuery().eq(SysUser::getAccount, account)
                .eq(SysUser::getLoginType, loginType)
                .one();
    }


}




